﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using server.DataBase;
using server.log;
using System.Net;

enum Permission {guest,user,moderator,admin}

namespace server.Communication.Messages
{
    public class ServerMessageHandler
    {
        private TcpClient client;
        private NetworkStream stream;
        private IFormatter formatter;
        private Data data;
        private int level;
        private int subPos;
        private int threadPos;
        private Permission permission;

        public ServerMessageHandler(TcpClient client, Data data)
        {
            this.client = client;
            this.formatter = new BinaryFormatter();
            this.stream = null;
            //this.data = new Data();
            //data.initData();
            this.data = data;
            this.level = 0;
            this.subPos = 0;
            this.threadPos=0;
            this.permission = Permission.guest;

        }
        public void handleConnect(Connect c)
        {
            switch (c.username)
            {
                case "default":
                    this.permission = Permission.guest;
                    send(new ConnectResult(true), this.stream);
                    break;
                default:
                    if (this.data.checkUser(c.username, c.password))
                    {
                        send(new ConnectResult(true), this.stream);
                        this.permission = this.data.getPermission(c.username);
                    }
                    else
                        send(new ConnectResult(false), this.stream);
                    break;
            }
        }
        public void handleRegister(Register r)
        {
            if (this.data.addUser(r.name, r.username, r.lastname, r.password, r.email))
            {
                //Logger.log(String.Format("in Register SEND: {0}", new RegisterResult(true).succ));
                send(new RegisterResult(true), this.stream);
            }
            else
            {
                send(new RegisterResult(false), this.stream);
            }
        }
        public void handleView(View v)
        {
            switch (this.level)
            {
                case 0:
                    send(new Page(this.data.creatPage(this.level, 0, 0)), this.stream);
                    break;
                case 1:
                    send(new Page(this.data.creatPage(this.level, v.choice - 1, 0)), this.stream);
                    this.subPos = v.choice - 1;
                    break;
                case 2:
                    send(new Page(this.data.creatPage(this.level, this.subPos, v.choice - 1)), this.stream);
                    this.threadPos = v.choice - 1;
                    break;
                default:
                    break;
            }
            this.level++;
        }
        public void handleCreatThread(CreateThread ct)
        {
            this.data.createThread(this.subPos, ct.subject, ct.body);
            Console.WriteLine(new Page(this.data.creatPage(this.level-1, this.subPos, 0)).page.ToString());
            send(new Page(this.data.creatPage(this.level-1, this.subPos, 0)), this.stream);
        }
        public void handleCreatePost(CreatePost cp)
        {
            this.data.createPost(this.subPos, this.threadPos, cp.subject, cp.body);
            send(new Page(this.data.creatPage(2, this.subPos, this.threadPos)), this.stream);
        }
        public void handleDisconnect()
        {
            this.permission = Permission.guest;
            send(new Success(), this.stream);
        }
        public void handleCreateSubForum(CreateSubForum sf)
        {
            this.data.createSubForum(sf.subject);
            send(new Success(), this.stream);
        }
        public void handleHelp()
        {
            switch (this.permission)
            {
                case Permission.guest:
                    send(new HelpResult("Register\nConnect\nBack"), this.stream);
                    break;
                case Permission.user:
                    send(new HelpResult("Disconnect\nCreateThread\nCreatePost\nBack"), this.stream);
                    break;
                case Permission.moderator:
                    send(new HelpResult("Disconnect\nCreateThread\nCreatePost\nBack"), this.stream);
                    break;
                case Permission.admin:
                    send(new HelpResult("Disconnect\nCreateThread\nCreatePost\nBack"), this.stream);
                    break;
                default:
                    break;
            }
        }
        private void handleBack()
        {
            switch (this.level-1)
            {
                case 0:
                    send(new PermitionDenied(), this.stream);
                    this.level++;
                    break;
                case 1:
                    send(new Page(this.data.creatPage(this.level-2, 0, 0)), this.stream);
                    break;
                case 2:
                    send(new Page(this.data.creatPage(this.level-2, this.subPos, 0)), this.stream);
                    break;
                default:
                    break;
            }
            this.level--;
        }

        public void proccessMsg(Message msg, NetworkStream strm)
        {
            Logger.log(String.Format("<IP:{0}> GET: {1}", ((IPEndPoint)client.Client.RemoteEndPoint).Address, msg.GetType()));

            this.stream = strm;
            string type = msg.GetType();
            switch (type)
            {
                case "Connect":
                    handleConnect((Connect)msg);
                    break;
                case "Register":
                    handleRegister((Register)msg);
                    break;
                case "View":
                    handleView((View)msg);
                    break;
                case "CreateThread":
                    handleCreatThread((CreateThread)msg);
                    break;
                case "CreatePost":
                    handleCreatePost((CreatePost)msg);
                    break;
                case "Disconnect":
                    handleDisconnect();
                    break;
                case "CreateSubForum":
                    handleCreateSubForum((CreateSubForum)msg);
                    break;
                case "Help":
                    handleHelp();
                    break;
                case "Back":
                    handleBack();
                    break;
                default:
                    Console.WriteLine("Illegal message type " + type);
                    break;
            }
        }


        private void send(Message msg, NetworkStream stream)
        {
            formatter.Serialize(stream, msg);
            Logger.log(String.Format("<IP:{0}> SEND: {1}", ((IPEndPoint)client.Client.RemoteEndPoint).Address, msg.GetType()));
        }
    }
}
